# Copyright 2015 the V8 project authors. All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
#       copyright notice, this list of conditions and the following
#       disclaimer in the documentation and/or other materials provided
#       with the distribution.
#     * Neither the name of Google Inc. nor the names of its
#       contributors may be used to endorse or promote products derived
#       from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import("//build/config/v8_target_cpu.gni")

declare_args() {
  # The v8 snapshot needs to be built by code that is compiled with a
  # toolchain that matches the bit-width of the target CPU, but runs on
  # the host.
  v8_snapshot_toolchain = ""
}

# Try to infer the appropriate snapshot toolchain for the v8_current_cpu
# where possible.
#
# Assume that v8_target_cpu (and hence v8_current_cpu) has been validated
# as supported on the current host CPU and OS in v8_target_cpu.gni. The
# logic below is complicated enough without also needing to do input
# validation.
#
# There are test cases for this code posted as an attachment to
# https://crbug.com/625353.

if (v8_snapshot_toolchain == "") {
  if (current_os == host_os && current_cpu == host_cpu) {
    # This is not a cross-compile, so build the snapshot with the current
    # toolchain.
    v8_snapshot_toolchain = current_toolchain
  } else if (current_os == host_os && current_cpu == "x86" &&
             host_cpu == "x64") {
    # This is an x64 -> x86 cross-compile, but x64 hosts can usually run x86
    # binaries built for the same OS, so build the snapshot with the current
    # toolchain here, too.
    v8_snapshot_toolchain = current_toolchain
  } else if (current_os == host_os && host_cpu == "arm64" &&
             current_cpu == "arm") {
    # Trying to compile 32-bit arm on arm64. Good luck!
    v8_snapshot_toolchain = current_toolchain
  } else if (host_cpu == "x64" && v8_current_cpu == "mips64") {
    # We don't support snapshot generation for big-endian targets,
    # therefore snapshots will need to be built using native mksnapshot
    # in combination with qemu
    v8_snapshot_toolchain = current_toolchain
  } else if (host_cpu == current_cpu) {
    # Cross-build from same ISA on one OS to another. For example:
    # * targeting win/x64 on a linux/x64 host
    # * targeting win/arm64 on a mac/arm64 host
    v8_snapshot_toolchain = host_toolchain
  } else if (host_cpu == "arm64" && current_cpu == "x64") {
    # Cross-build from arm64 to intel (likely on an Apple Silicon mac).
    v8_snapshot_toolchain =
        "//build/toolchain/${host_os}:clang_arm64_v8_$v8_current_cpu"
  } else if (host_cpu == "x64") {
    # This is a cross-compile from an x64 host to either a non-Intel target
    # cpu or to 32-bit x86 on a different target OS.

    assert(v8_current_cpu != "x64", "handled by host_cpu == current_cpu branch")
    if (v8_current_cpu == "x86") {
      _cpus = v8_current_cpu
    } else if (v8_current_cpu == "arm64" || v8_current_cpu == "mips64el" ||
               v8_current_cpu == "riscv64" || v8_current_cpu == "loong64") {
      if (is_win && v8_current_cpu == "arm64") {
        # set _cpus to blank for Windows ARM64 so host_toolchain could be
        # selected as snapshot toolchain later.
        _cpus = ""
      } else {
        _cpus = "x64_v8_${v8_current_cpu}"
      }
    } else if (v8_current_cpu == "arm" || v8_current_cpu == "riscv32") {
      _cpus = "x86_v8_${v8_current_cpu}"
    } else {
      # This branch should not be reached; leave _cpus blank so the assert
      # below will fail.
      _cpus = ""
    }

    if (_cpus != "") {
      v8_snapshot_toolchain = "//build/toolchain/${host_os}:clang_${_cpus}"
    } else if (is_win && v8_current_cpu == "arm64") {
      # cross compile Windows arm64 with host toolchain.
      v8_snapshot_toolchain = host_toolchain
    }
  } else if (host_cpu == "arm64" && current_cpu == "arm64" &&
             host_os == "mac") {
    # cross compile iOS arm64 with host_toolchain
    v8_snapshot_toolchain = host_toolchain
  }
}

assert(v8_snapshot_toolchain != "",
       "Do not know how to build a snapshot for $current_toolchain " +
           "on $host_os $host_cpu")

# We reuse the snapshot toolchain for building torque and other generators to
# avoid building v8_libbase on the host more than once. On mips with big endian,
# the snapshot toolchain is the target toolchain and, hence, can't be used.
v8_generator_toolchain = v8_snapshot_toolchain
if (host_cpu == "x64" && v8_current_cpu == "mips64") {
  v8_generator_toolchain = "//build/toolchain/linux:clang_x64"
}
